home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
byte1286.arc
/
DIRDEMO.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1986-10-29
|
9KB
|
287 lines
program DirectoryDemo;
{
Demonstration of how to search a PC-DOS/MS-DOS file directory for
a file specification, which can contain global characters ('*' and '?'),
using DOS function calls hex 4E and hex 4F. Displays a list of names
and sizes of files which match the specification.
Program compiles correctly under versions 2 and 3 of Turbo Pascal.
Tested under IBM PC-DOS ver 2.10 and 3.0, and Compaq MS-DOS 2.11.
Copyright June 1985 by D.F. Yriart.
Sub-directory attribute test modified 28 July 1985.
}
type
UserSpec = string[64];
Registers = record
AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : Integer;
end;
FileName = string[13];
DTAPointer = ^DTARecord;
DTARecord = record { Layout of DTA on return from calls }
DOSReserved : array[1..21] of byte;
Attribute : byte;
FileTime, { packed in special format }
FileDate, { " " " " }
SizeLow,
SizeHigh : integer;
FoundName : array[1..13] of char;
end;
const
NUL = ^@; { character 0, used to terminate ASCIIZ string }
SeekAttrib = $10; { search for files & sub-directories }
var
TransferRec : DTAPointer; { will point to program DTA }
MatchPtrn : UserSpec; { in Turbo Pascal string format }
RetName : FileName; { name found by call }
FilSize : Real; { size of file found }
Count : Integer;
NoFind, LastFile,
SubDirec : Boolean;
procedure PointDTA(Var DTARec : DTAPointer);
{
Use function hex 2F to locate the starting address of the Data
Transfer Area (DTA) and point to it.
Pointer will be used by file match procedures to find the data
returned in the DTA.
}
Const GetDTA = $2F00; { function number }
var
Regs : Registers;
Begin
Regs.AX := GetDTA; { load function number }
MsDos(Regs); { make call to DOS }
{ On return from call to GetDTA, ES register contains DTA segment
address, BX register contains DTA offset in segment }
DTARec := Ptr(Regs.ES,Regs.BX); { Set pointer }
End;
function SizeOfFile(HiWord, LoWord : Integer) : Real;
{
Converts the file size returned by DOS in two 16 bit words (unsigned
integers) into a real number.
}
Var
BigNo, Size : Real;
Begin
BigNo := (MaxInt * 2.0) + 2;
if HiWord < 0 then Size := (BigNo + HiWord) * BigNo
else Size := HiWord * BigNo;
if LoWord >= 0 then Size := Size + LoWord
else Size := Size + (BigNo + LoWord);
SizeOfFile := Size
End;
procedure FindFirst(Pattern : UserSpec; Var Found : FileName; Var Size : Real;
Var NoMatch : Boolean; Var LastOne : Boolean;
Var SubDir : Boolean);
{
Function hex 4E returns first file name that matches user's specification.
If an error occurs, the carry flag will be set and DOS will return error
code 2 or 18 in the AX register. The procedure sets NoMatch and LastOne
depending on the error code.
The filespec to search for must be stored as an ASCIIZ string, terminated
by a byte of binary zeros (character NUL). When the call is made, the
DS and DX registers point to the ASCIIZ string.
The file attribute to search for can be loaded in the CX register.
If a match occurs, the DTA will be loaded with information about
the file which was found. This procedure recovers the file name and
attribute of the found file. SubDir returns true if the file's
attribute is "subdirectory".
}
Const FindFirst = $4E00; { function number }
Type
ASCIIZ = array[1..64] of char;
var
FileSpec : ASCIIZ; { search pattern in DOS ASCIIZ string format }
Regs : Registers;
PosInStr,
Count : Integer;
FoundLen : Byte absolute Found;
Begin
{ Convert the file name to an ASCIIZ string for the function call. }
for PosInStr := 1 to length(Pattern) do
FileSpec[PosInStr] := Pattern[PosInStr];
FileSpec[length(Pattern) + 1] := NUL;
With Regs do
begin
DS := Seg(FileSpec); { Point to ASCIIZ string }
DX := Ofs(FileSpec);
CX := SeekAttrib; { File attribute to look for }
AX := FindFirst; { load function number }
MsDos(Regs);
if (Flags and 1) > 0 then { test carry flag }
begin { Handle error return codes }
Case AX of
2 : begin { No match }
NoMatch := True;
LastOne := True;
end;
18 : begin { No more files }
NoMatch := False;
LastOne := True;
end;
else
writeln(^G'Can''t interpret error return code');
Halt;
end; { Case }
end
else
begin { No error return code }
NoMatch := False;
LastOne := False;
end;
end; { with Regs }
{ Capture returned file name and attribute, other information
such as file size, time and date is also returned in the DTA.
TransferRec points to the record superimposed on the DTA. }
if (not NoMatch) then
with TransferRec^ do
begin
Found := FoundName;
{ Find number of characters returned in the file name area }
Count := 0;
While Found[Count] <> NUL do Count := Count + 1;
FoundLen := Count; { set the length of the name string }
{ Blank out any garbage characters passed from the DTA }
For Count := length(Found) + 1 to 13 do Found := Found + ' ';
{ Test whether the file is a subdirectory and set flag. }
if (Attribute and SeekAttrib) > 0 then SubDir := True
else SubDir := False;
{ Get the file size if file is not a subdirectory. }
if not SubDir then Size := SizeOfFile(SizeHigh,SizeLow)
else Size := 0.0;
end; { with TransferRec }
End;
procedure FindNext(Var Found : FileName; Var Size : Real;
Var LastOne : Boolean; Var SubDir : Boolean);
{
Function hex 4F returns next matching file name. When error 18 is
returned there are no more matches. The search criteria set up by
function hex 4E are used by this call, and information is returned
in the DTA as described for procedure FindFirst.
}
Const FindNext = $4F00; { function number }
var
Regs : Registers;
Count : Integer;
FoundLen : Byte absolute Found;
Begin
With Regs do
begin
AX := FindNext;
MsDos(Regs);
if (Flags and 1) > 0 then { Handle error return codes }
if AX = 18 then LastOne := True { No more files }
else
begin
writeln(^G'Can''t interpret error return code');
Halt;
end
else LastOne := False; { No error return code }
end; { with Regs }
{ Capture returned file name and attribute }
with TransferRec^ do
begin
Found := FoundName;
{ Set length of file name and clear "garbage." }
Count := 0;
While Found[Count] <> NUL do Count := Count + 1;
FoundLen := Count;
For Count := length(Found) + 1 to 13 do Found := Found + ' ';
{ Test for subdirectory. }
if (Attribute and SeekAttrib) > 0 then SubDir := True
else SubDir := False;
{ Get the file size if file is not a subdirectory. }
if not SubDir then
Size := SizeOfFile(SizeHigh,SizeLow)
else Size := 0.0;
end; { with TransferRec }
End;
{
**********************************
* MAIN PROGRAM *
**********************************
}
BEGIN
ClrScr;
writeln(' -- Demonstration of Directory Search Calls --');
write(' Find? ');
readln(MatchPtrn); { The user's search specification }
writeln;
Count := 0;
PointDTA(TransferRec); { Set the DTA pointer }
{ Call function hex 4E to search for first match. }
FindFirst(MatchPtrn,RetName,FilSize,NoFind,LastFile,SubDirec);
if NoFind or LastFile then writeln('File not found.')
else
begin
{ Display additional matches and keep looking until no
more are found. Display in three columns. }
While (not LastFile) do
begin
if SubDirec then LowVideo; { Display subdirectories in }
write(RetName,' ',FilSize:8:0,' '); { low intensity. }
NormVideo;
Count := Count + 1;
if (Count mod 3) = 0 then Writeln;
{ Call function hex 4F to search for another match. }
FindNext(RetName,FilSize,LastFile,SubDirec);
end;
end;
{ Close up the display with a count of files found. }
if (Count mod 3) <> 0 then writeln;
writeln;
write('*** ',Count,' Files or ');
LowVideo;
write('Sub-Directories');
NormVideo;
writeln(' found ***');
END.
** '